<template>
	<div class="notice-bar" :style="{ background, height: `${height}px` }" v-show="!state.isMode">
		<div class="notice-bar-warp" :style="{ color, fontSize: `${size}px` }">
			<HIcon v-if="leftIcon" :name="leftIcon" class="notice-bar-warp-left-icon" />
			<div class="notice-bar-warp-text-box" ref="noticeBarWarpRef">
				<div v-if="!scrollable" class="notice-bar-warp-text" ref="noticeBarTextRef">{{ text }}</div>
				<div v-else class="notice-bar-warp-slot"><slot></slot></div>
			</div>
			<HIcon
				v-if="rightIcon"
				:name="rightIcon"
				class="notice-bar-warp-right-icon"
				@click="onRightIconClick"
			/>
		</div>
	</div>
</template>

<script setup lang="ts" name="noticeBar">
import { reactive, ref, onMounted, nextTick } from "vue";

// 定义父组件传过来的值
interface noticeBarProps {
	mode?: "normal" | "closeable" | "link"; // 通知栏模式
	text?: string; // 通知文本内容
	color?: string; // 通知文本颜色
	background?: string; // 通知背景色
	size?: number | string; // 字体大小 (px)
	height?: number; // 通知栏高度 (px)
	delay?: number; // 动画延迟时间 (s)
	speed?: number; // 滚动速率 (px/s)
	scrollable?: boolean; // 是否开启垂直滚动
	leftIcon?: string; // 自定义左侧图标
	rightIcon?: string; // 自定义右侧图标
}
const props = withDefaults(defineProps<noticeBarProps>(), {
	mode: "normal",
	text: "",
	color: "var(--el-color-warning)",
	background: "var(--el-color-warning-light-9)",
	size: 14,
	height: 40,
	delay: 1,
	speed: 100,
	scrollable: false,
	leftIcon: "",
	rightIcon: "",
});

// 定义子组件向父组件传值/事件
const emit = defineEmits(["close", "link"]);

// 定义变量内容
const noticeBarWarpRef = ref();
const noticeBarTextRef = ref();
const state = reactive({
	order: 1,
	oneTime: 0,
	twoTime: 0,
	warpOWidth: 0,
	textOWidth: 0,
	isMode: false,
});

// 初始化 animation 各项参数
const initAnimation = () => {
	nextTick(() => {
		state.warpOWidth = noticeBarWarpRef.value.offsetWidth;
		state.textOWidth = noticeBarTextRef.value.offsetWidth;
		document.styleSheets[0].insertRule(
			`@keyframes oneAnimation {0% {left: 0px;} 100% {left: -${state.textOWidth}px;}}`
		);
		document.styleSheets[0].insertRule(
			`@keyframes twoAnimation {0% {left: ${state.warpOWidth}px;} 100% {left: -${state.textOWidth}px;}}`
		);
		computeAnimationTime();
		setTimeout(() => {
			changeAnimation();
		}, props.delay * 1000);
	});
};
// 计算 animation 滚动时长
const computeAnimationTime = () => {
	state.oneTime = state.textOWidth / props.speed;
	state.twoTime = (state.textOWidth + state.warpOWidth) / props.speed;
};
// 改变 animation 动画调用
const changeAnimation = () => {
	if (state.order === 1) {
		noticeBarTextRef.value.style.cssText = `animation: oneAnimation ${state.oneTime}s linear; opactity: 1;}`;
		state.order = 2;
	} else {
		noticeBarTextRef.value.style.cssText = `animation: twoAnimation ${state.twoTime}s linear infinite; opacity: 1;`;
	}
};
// 监听 animation 动画的结束
const listenerAnimationend = () => {
	noticeBarTextRef.value.addEventListener(
		"animationend",
		() => {
			changeAnimation();
		},
		false
	);
};
// 右侧 icon 图标点击
const onRightIconClick = () => {
	if (props.mode === "normal") return false;
	if (props.mode === "closeable") {
		state.isMode = true;
		emit("close");
	} else if (props.mode === "link") {
		emit("link");
	}
};
// 页面加载时
onMounted(() => {
	if (props.scrollable) return false;
	initAnimation();
	listenerAnimationend();
});
</script>

<style scoped lang="scss">
.notice-bar {
	padding: 0 15px;
	width: 100%;
	border-radius: 4px;
	.notice-bar-warp {
		display: flex;
		align-items: center;
		width: 100%;
		height: inherit;
		.notice-bar-warp-text-box {
			flex: 1;
			height: inherit;
			display: flex;
			align-items: center;
			overflow: hidden;
			position: relative;
			.notice-bar-warp-text {
				white-space: nowrap;
				position: absolute;
				left: 0;
			}
			.notice-bar-warp-slot {
				width: 100%;
				white-space: nowrap;
				:deep(.el-carousel__item) {
					display: flex;
					align-items: center;
				}
			}
		}
		.notice-bar-warp-left-icon {
			width: 24px;
			font-size: inherit !important;
		}
		.notice-bar-warp-right-icon {
			width: 24px;
			text-align: right;
			font-size: inherit !important;
			justify-content: flex-end;
			&:hover {
				cursor: pointer;
			}
		}
	}
}
</style>
